package pl.edu.agh.gt.strategy;

import org.apache.log4j.Logger;

import pl.edu.agh.gt.data.Rate;

public class GreedyStrategy extends Strategy {

	private final static Logger log = Logger.getLogger(GreedyStrategy.class);
	
	private final static int MAX_IN_THE_MARKET = 256; // large value to stay very long
	public final static float maxLoss = -10;
	public final static float desiredEarn = 5;

	// parameters
	public float greedA = 10;
	//public float maxLoss = -50; juz nie parametr
	//public float desiredEarn = 1;
	public float enteringValue = 1000;
	public float lossTolerancy = 0;
	// public final float greedB = 0;
	// public final int resolution = 1;
	
	private int iterationEntered;

	public GreedyStrategy(double lt, double ga, double de_IGNORED, double ev, double ml_IGNORED) {
		// resolution = r;
		greedA = (float) ga;
		// greedB = (float) gb;
		// maxLoss = (float) ml;
		//desiredEarn = (float) de;
		enteringValue = (float) ev;
		lossTolerancy = (float) lt;
	}

	public GreedyStrategy() {
	}

	// variables
	private float currEarn;
	private Rate  currRate;

	private void close(Context ctx) {
		currEarn = 0;
		ctx.trader.close(currRate);
	}

	@Override
	public void decide(int iteration, Rate rate, Context ctx) {

		currRate = rate;

		log.debug("Invested = " + ctx.trader.invested + " (max = " + ctx.trader.maxInvested + ")");

		if (ctx.trader.invested == 0) {
			// enter the market
			iterationEntered = iteration;
			// currEarn will be negative because of spread
			currEarn = ctx.broker.bid(currRate, ctx.broker.ask(currRate, enteringValue)) - enteringValue;

			log.debug("Entering market " + enteringValue);
			ctx.trader.buy(enteringValue, currRate);

		} else {

			float prevEarn = currEarn;
			currEarn = ctx.broker.bid(currRate, ctx.trader.quoteCurrency) - ctx.trader.invested;

			log.debug("CURR EARN = " + currEarn + ", prev earn = " + prevEarn);
			
			// zbyt dlugo na rynku
			if( iteration > iterationEntered + MAX_IN_THE_MARKET ) {
				log.debug("CLOSING !!! ######################################################### \t TOO LONG IN THE MARKET \t "
						+ currEarn);
				close(ctx);
			}
			// tracimy
			else if (currEarn < prevEarn) {

				// przecholowalismy?
				if (currEarn < maxLoss) {
					// close
					log.debug("CLOSING !!! >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> \t MINUS \t "
							+ currEarn);
					close(ctx);
				} else {
					// buy
					float loss = (prevEarn - currEarn);
					assert loss > 0;
					if (loss > lossTolerancy) { // ograniczenie
												// czestotliwosci kupna
												// (strata wieksza niz prog)

						float more = greedA * loss;
						log.debug(" ============================================================================= BUYING MORE += "
								+ more);

						// zabezpieczenia przed nieprawidlowymi wartosciami
						if (more <= 0)
							return;
						if (more > ctx.trader.baseCurrency)
							more = ctx.trader.baseCurrency;

						ctx.trader.buy(more, currRate);
					} else {
						// do nothing
					}
				}

			} else {

				// zarobilismy ile chcielismy, zamykamy
				if (currEarn > desiredEarn) {
					// close
					log.debug("CLOSING !!! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< \t PLUS \t "
							+ currEarn);
					close(ctx);
				} else {
					// wait
					log.debug("WAITING");
				}
			}

		}

	}

	@Override
	public String toString() {
		StringBuffer sb = new StringBuffer();
		sb.append("lossTolerancy = " + lossTolerancy);
		sb.append(",greedA = " + greedA);
		//sb.append(",desiredEarn = " + desiredEarn);
		sb.append(",enteringValue = " + enteringValue);
		//sb.append(",maxLoss = " + maxLoss);
		
		return sb.toString();
	}

}
